/**
 * 
 */
package bancosys.tec.services.implementor.descriptor;

import jmine.tec.di.resolver.ObjectResolver;
import jmine.tec.di.scope.TypedScope;
import jmine.tec.di.type.TypeConvertionException;
import jmine.tec.di.wrapper.Wrapper;
import jmine.tec.services.api.ServiceProperties;

/**
 * {@link ObjectResolver} para o proprio {@link TypedScope}. Vai injetar o {@link TypedScope} sendo usado no momento em que for chamado
 * 
 * @author takeshi
 */
final class ScopeResolver implements ObjectResolver {

    /**
     */
    private ScopeResolver() {
    }

    private static final ScopeResolver INSTANCE = new ScopeResolver();

    /**
     * @return {@link ScopeResolver}
     */
    public static ScopeResolver getInstance() {
        return INSTANCE;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isResolvable(TypedScope properties) {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isStatic() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Object resolveObject(TypedScope properties, Wrapper wrapper, Class<?> requiredComponentClass) throws TypeConvertionException {
        return wrapper.wrap("<auto>", toServiceProperties(properties), requiredComponentClass);
    }

    /**
     * @param properties {@link TypedScope}
     * @return {@link ServiceProperties}
     */
    private ServiceProperties toServiceProperties(TypedScope properties) {
        if (properties instanceof ServiceProperties) {
            return (ServiceProperties) properties;
        }
        throw new IllegalStateException("cannot convert from: " + properties.getClass() + " to " + ServiceProperties.class);
    }

    /**
     * {@inheritDoc}
     */
    public boolean isTypeCompatible(Class<?> declaredRawType) {
        return declaredRawType.isAssignableFrom(TypedScope.class) || declaredRawType.isAssignableFrom(ServiceProperties.class);
    }

    /**
     * @return {@link Object}
     */
    protected Object readResolve() {
        return INSTANCE;
    }

}